package cn.monkey.config;

import cn.monkey.filter.JwtTokenFilter;
import cn.monkey.mapper.MenuMapper;
import cn.monkey.mapper.RoleMapper;
import cn.monkey.pojo.Menu;
import cn.monkey.utils.JwtUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

@Configuration
public class WebSecurityConfig {
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    WebSecurityCustomizer webSecurityCustomizer(){
        return (web -> web.ignoring().requestMatchers("/images/**","/js/**","/apk/**"));
    }

    @Autowired
    MenuMapper menuMapper;
    @Autowired
    RoleMapper roleMapper;

    @Autowired
    JwtTokenFilter jwtTokenFilter;

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
        http.formLogin(
                login->login.loginProcessingUrl("/login")
                        .successHandler((request,response,authentication)->{
                            response.setContentType("application/json;charset=utf-8");
                            String token = JwtUtil.createToken(authentication);
                            response.getWriter().write(token);
                        })
                        .failureHandler((request,response,authentication)->{
                            response.setContentType("application/json;charset=utf-8");
                            response.getWriter().write("登录失败");
                        })
        );
        http.authorizeHttpRequests(ahr->
                ahr.requestMatchers("/login","error").permitAll()
                        .anyRequest().access((authentication,object)->{
                            String uri = object.getRequest().getRequestURI();
                            List<Menu> menus = menuMapper.getMenuUrl();
                            boolean quanxian=false;
                            for (Menu menu : menus) {
                                if(uri.startsWith(menu.getUrl())){
                                    quanxian=true;
                                    List<String> roleName= roleMapper.getRoleNameByMid(menu.getMid());
                                    Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities();
                                    for (GrantedAuthority authority : authorities) {
                                        if(roleName.contains(authority.getAuthority())){
                                            return new AuthorizationDecision(true);
                                        }
                                    }
                                }
                            }
                            if(!quanxian && !(authentication.get() instanceof AnonymousAuthenticationToken)){
                                return new AuthorizationDecision(true);
                            }
                            System.out.println("无权访问");
                            return new AuthorizationDecision(false);
                        })
        );
        return http.build();
    }
}
